package study;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

import java.util.ArrayList;
import java.util.List;

/***
 *   疑问 ： @SentinelResource注解的方式无效，不知道啥原因。
 */
public class SentinelMain {
    //资源名称 其中，resourceName可以定义方法名称、接口名称或者其他的唯一标识
    public static final String resourceName = "MyResource";
    public static void main(String[] args) {

        SentinelMain sentinelMain = new SentinelMain();
        sentinelMain.initFlowRules();
        while (true){
            doSomething1();
//            doSomething2();
//            sentinelMain.doSomething3("222");
            // sentinelMain.doSomething4();

        }

    }
    //使用方式一
    private static void doSomething1(){
        //定义资源
        try(Entry entry = SphU.entry(resourceName)){
            //业务逻辑处理
            System.out.println("hello- "+System.currentTimeMillis());
        }catch (BlockException e){
            //限流时的处理
            System.out.println("被限流");
        }
    }
    //使用方式二
    private static void doSomething2(){
        //定义资源
        if( SphO.entry(resourceName)){
            try{
                //业务逻辑处理
                System.out.println("hello- "+System.currentTimeMillis());
            }finally{
                //注意资源使用完之后要调用Sph0.exit（），否则会导致调用链记录异常，抛出ErrorEntryFreeException异常。
                SphO.exit();
            }
        }else{
            //限流时的处理
            System.out.println("被限流");
        }
    }
    //使用方式三
    @SentinelResource(value = resourceName,blockHandler="blockErrorHandel" )
    public  void doSomething3(String name){
        //业务逻辑处理
        System.out.println(name+"-业务逻辑处理");
    }
    //这个方法的定义必须和原始方法getUserById的返回值、参数保持一致，而且需要增加BlockException参数。
    public  void blockErrorHandel(String name ,BlockException e){
        System.out.println(name+"-被限流 -blockErrorHandel 处理");
    }
    //使用方式四
    @SentinelResource(value=resourceName,blockHandler="blockErrorHandel2",fallback = "fallbackHandel")
    public  String  doSomething4(){
        //业务逻辑处理

        System.out.println("-业务逻辑处理");
        return "2323";
    }
    //这个方法的定义必须和原始方法getUserById的返回值、参数保持一致，而且需要增加BlockException参数。
    public  String blockErrorHandel2(BlockException e){
        System.out.println("-被限流 -blockErrorHandel 处理");
        return "被限流 ";
    }
    public  String fallbackHandel(){
        System.out.println("-回调处理 -fallbackHandel 处理");
        return "回调处理 ";
    }
    //限流规则定义
    public static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule flowRule = new FlowRule();
        flowRule.setResource(resourceName);
        flowRule.setCount(20);
        //限流阈值类型，QPS模式（1）或并发线程数模式（0）。
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rules.add(flowRule);
        FlowRuleManager.loadRules(rules);

    }
}
